搞了个遥控车,结果只有几十米的遥控距离,只能自己玩,这就很不爽。如果可以用手机控制,那么就可以让别的朋友,隔着几千里都能玩了。
说干就干,首先买个板子。
搞了个esp8266,可以输出pwm,并且有wifi模块,还支持python编程,这一下子就变成小孩子都能做的东西了。
还需要买一个电机驱动板,用来控制点击。
总体逻辑为:
1.通过驱动板来控制电机前进后退。
2.通过板子输出pwm来控制舵机的转动。
随便写几行代码。
from simple import MQTTClient
import network
import time
from machine import Pin, Timer, PWM
# 主要完成以下功能
# 1. 控制1个电机 控制命令[1:加速 2:减速 3:定速]
# 2. 实现踩下油门(加速)功能
# 3. 实现放下油门(减速)功能
# 4. 实现定速功能
# 5. 实现电机正反转 控制命令[4:正转 5:反转]
# 6. 实现转弯功能,具体表现为控制一个舵机,实现为pwm输出
# 7. 能够停止 控制命令[2]
# 控制命令
# 1加速 101减速 3定速 2停止 4左转 104左回正 5右转 105右回正 6倒车 7前进
# 默认是stop状态,开机需要先前进才可以
# 配置信息
MAX_SPEED = 1023 # 最大速度
MIN_SPEED = 150 # 最小速度
LEFT_ANGLE = 45 # 左转的角度
RIGHT_ANGLE = 135 # 左转的角度
# 无线网连接信息
SSID = "mxblog.mxguanwang.cn"
PASSWORD = "mx88888888"
# 服务器连接信息
SERVER = "mettserver"
CLIENT_ID = "clientid"
TOPIC = b"yourtopic"
username = 'name'
password = 'password'
# IO使用情况
# D1:控制电机速度 pwm
# D2,D3:控制电机正反转[1,0正转0,1反转0,0刹车1,1悬空]
# D4舵机 pwm 舵机逻辑为,pwm超过1.5ms正转2.5ms转一圈 小于1.5ms反转(1ms一圈0.5以下的被忽略)
# D5 被D4使用
# 这里假设左转是倒转,右转是正转
# P2 板子上的灯用来表示连接成功。1灯灭,未初始化完成,0灯亮,服务器连接成功
D1 = Pin(5, Pin.OUT, value=1)
D2 = Pin(4, Pin.OUT, value=1)
D3 = Pin(0, Pin.OUT, value=1)
D4 = Pin(14, Pin.OUT, value=1)
P2 = Pin(2, Pin.OUT, value=1)
sp_pwm = PWM(D1, 1000) # 速度是持续性的,影响不大
fx_pwm = PWM(D4, 50) # 舵机0.5ms-2.5ms其中0.5-1.5正转1.5-2.5反转
# 使用500 则50%为1ms 100%为2ms实现正反转 转速53-62r/min
# 所以占空比500/1000应该就是1秒1圈
# 状态信息
speed = 0 # 速度(0-1023)
state = 0 # 状态(初始0:加速:1 减速:2 定速:3)
lastspeed = 0 # 上次的速度,用来判断是否需要发送速度
sendidx = 0 # 每10次发一次
fx = 0 # 暂时修改为只能偏移到底不支持 微调[0:初始值中间1:向左2:向右]
back = False # 是否是倒车
curangle = 90 # 当前的舵机角度
# 踩下油门(加速)
def OnAddSpeed():
global state, speed
if speed >= MAX_SPEED:
state = 0
speed = MAX_SPEED
return
state = 1
# 松开油门(减速)
def OnDecSpeed():
global state, speed
if speed <= MIN_SPEED:
state = 0
speed = MIN_SPEED
return
state = 2
def Revolve(angle):
global curangle
if fx == 0:
curangle = 90
elif fx == 1:
curangle = LEFT_ANGLE
elif fx == 2:
curangle = RIGHT_ANGLE
else:
return
# 如果目标角度大约当前角度则增加 否则则减少
idx = 1
if angle < curangle:
idx = -1
for i in range(curangle,angle,idx):
fx_pwm.duty(int(125-i/180*100))
time.sleep(0.0025)
curangle = angle
# 左转
def OnLeft():
global fx
# 如果已经是左转了,那么就不处理
if fx == 1:
return
Revolve(LEFT_ANGLE)
fx = 1
# 右转
def OnRight():
global fx
# 如果已经是右转了,那么就不处理
if fx == 2:
return
Revolve(RIGHT_ANGLE)
fx = 2
# 中间
def OnCenter():
global fx
if fx == 0:
return
Revolve(90)
fx = 0
# 前进
def OnFace():
global back
if back:
OnNull()
D2.value(1)
D3.value(0)
back = False
# 后退
def OnBack():
global back
if back:
return
else:
OnNull()
D2.value(0)
D3.value(1)
back = True
# 停止
def OnStop():
OnNull()
D2.value(0)
D3.value(0)
# 悬空
def OnNull():
global back
back = False
D2.value(1)
D3.value(1)
time.sleep(0.005)
# 接收消息处理
def OnMsg(topic, msg):
# 过滤自己发送的消息
if len(msg) > 1:
stype = msg[0:2]
if stype == b'sp':
return
global state
print((topic, msg))
cmd = msg
if cmd == b'1':
print("加速")
OnAddSpeed()
return
if cmd == b'101':
print("减速")
OnDecSpeed()
return
if cmd == b'103':
# 如果当前已经是定速,则取消定速,进入减速状态
print("定速")
if state == 3:
state = 2
else:
state = 3
return
if cmd == b'2':
print("停止")
sp_pwm.duty(0)
state = 0
return
if cmd == b'4':
print("向左")
OnLeft()
return
if cmd == b'104':
print("左回正")
OnCenter()
return
if cmd == b'5':
print("向左")
OnRight()
return
if cmd == b'105':
print("右回正")
OnCenter()
return
if cmd == b'6':
print("倒车")
OnBack()
return
if cmd == b'7':
print("前进")
OnFace()
return
return
# 连接无线网
def connectWifi(ssid, passwd):
print("开始连接无线网")
wlan = network.WLAN(network.STA_IF) # create a wlan object
# wlan.active(False)
wlan.active(True) # Activate the network interface
wlan.disconnect() # Disconnect the last connected WiFi
wlan.connect(ssid, passwd) # connect wifi
while (wlan.ifconfig()[0] == '0.0.0.0'):
time.sleep(1)
print("无线网连接完成")
# 定时更新状态 4秒内速度加满 每秒进来100次所以每次增加1024/4/100
def UpdateState(id):
global state, speed, sendidx, lastspeed
if sendidx < 10:
sendidx += 1
else:
sendidx = 0
if lastspeed != speed:
conn.publish(TOPIC, "sp:" + str(speed))
lastspeed = speed
if state == 1:
speed += 1024 / 4 / 100
elif state == 2:
speed -= 1024 / 4 / 100
else:
return
# 标准化数据
if speed > MAX_SPEED:
speed = MAX_SPEED
elif speed < MIN_SPEED:
speed = MIN_SPEED
# 速度不变就跳过
if int(speed) == sp_pwm.duty():
return
# print("\r当前状态" + str(state) + "当前速度" + str(speed))
sp_pwm.duty(int(speed))
P2.value(1)
# 顺序:连接wifi -> 连接服务器 -> 订阅 -> 等待
wlan = connectWifi(SSID, PASSWORD)
conn = MQTTClient(CLIENT_ID, SERVER, 0, username, password)
conn.set_callback(OnMsg)
print("开始连接服务器")
conn.connect()
print("服务器连接完成\n开始订阅")
conn.subscribe(TOPIC)
print("订阅完成")
# 启动定时器,定时更新状态
tim = Timer(1)
tim.init(period=10, mode=Timer.PERIODIC, callback=UpdateState)
print("Connected to %s, subscribed to %s topic" % (SERVER, TOPIC))
sp_pwm.duty(MIN_SPEED)
OnStop()
P2.value(0)
while True:
conn.wait_msg()
uPyCraft 烧录一下,soeasy
接线如下:




然后手机上搞个测试app,搞几个按钮,发送mqtt命令就可以控制了。
经过测试,延迟不大,基本上满足需求。
可以从代码中提取的东西:
- 1.mqtt接收消息
- 2.连接wifi
- 3.输出pwm
- 4.定时器
- 5.控制舵机
- 6.一种油门控制的实现方案
一个人活着,不是为了改变什么,而是为了在这个世界上留下点什么。如果某天,这篇文章帮到了你了,欢迎打赏,一分也是爱,并且以后如果实现了打赏墙,还可以上墙。
Comments | 4 条评论
好像发不出去
@刘善弛 不好意思, 其实今天看到邮件了,就是工作有点忙,没有来得及回复。
您好 这个是通过手机 APP 通过网络将指令发送至遥控车上实现控制么。
@刘善弛 是的,直接手机app就可以控制。